<?php defined('SYS_PATH') or die('No direct script access.');
/**
 * Memcache class
 *
 * @author zendzhang<zendzhang@hotmail.com>
 * @version $Id$
 */
class TrueBlood_Mc extends TrueBlood
{
    /**
     * Configuration
     *
     * @var array
     */
    protected $_config = array
    (
        array
        (
            'host' => '127.0.0.1',
            'port' => 11211,
            'persistent' => true,
            'timeout' => 1,
            'expire' => 0
            )
        );

    /**
     * Memcached connection
     *
     * @var objcet
     */
    protected $_connection;

    /**
     * An array of memcache instances
     *
     * @var array
     */
    protected static $_instances = array();

    /**
     * Returns a singleton instance of Memcache
     *
     * @param string $name
     * @param object $
     */
    public static function &instance($name)
    {
        if (!isset(self::$_instances[$name]))
        {
            $memcaches = self::$load->config('memcaches');
            if (!isset($memcaches[$name]))
            {
                throw new TrueBlood_Exception("memcaches.{$name} undefined, check configs/memcaches.inc.php");
            }
            self::$_instances[$name] = new self($memcaches[$name]);
        }
        return self::$_instances[$name];
    }

    /**
     * Constructor
     *
     * @param array $config
     */
    public function __construct(array $config = null)
    {
        if (null === $config)
        {
            $memcaches = $this->load->config('memcaches');
            if (isset($memcaches['default']))
            {
                $config = $memcaches['default'];
            }
        }
        $this->_config = (array)$config + $this->_config;

        $this->log('debug', 'TrueBlood_Mc Class Initialized');

        $this->connect();
    }

    /**
     * Connect to Memcached
     *
     * @return resource
     */
    public function connect()
    {
        if (!extension_loaded('memcache'))
        {
            throw new TrueBlood_Exception('Can not find memcache extension.');
        }
        $this->_connection = new Memcache();
        foreach ($this->_config as $server)
        {
            $server += array('host' => '127.0.0.1', 'port' => 11211, 'persistent' => true, 'timeout' => 1);
            $this->_connection->addServer($server['host'], $server['port'], $server['persistent'], $server['timeout']);
        }
    }

    /**
     * Returns the value stored in the memory by it's key
     *
     * @param string $key
     * @return mixed
     */
    public function get($key)
    {
        return $this->_connection->get($key);
    }

    /**
     * Store the value in the memcache memory (overwrite if key exists)
     *
     * @param string $key
     * @param mixed $value
     * @param bool $compress
     * @param int $expire (seconds before item expires)
     * @return bool
     */
    public function set($key, $value, $compress = false, $expire = null)
    {
        if (null === $expire)
        {
            $expire = isset($this->_config[0]['expire']) ? (int) $this->_config[0]['expire'] : 0;
        }
        return $this->_connection->set($key, $value, $compress ? MEMCACHE_COMPRESSED : null, $expire);
    }

    /**
     * Set the value in memcache if the value does not exist; returns false if value exists
     *
     * @param sting $key
     * @param mixed $value
     * @param bool $compress
     * @param int $expire
     * @return bool
     */
    public function add($key, $value, $compress = false, $expire = null)
    {
        if (null === $expire)
        {
            $expire = isset($this->_config[0]['expire']) ? (int) $this->_config[0]['expire'] : 0;
        }
        return $this->_connection->add($key, $value, $compress ? MEMCACHE_COMPRESSED : null, $expire);
    }

    /**
     * Replace an existing value
     *
     * @param string $key
     * @param mixed $value
     * @param bool $compress
     * @param int $expire
     * @return bool
     */
    public function replace($key, $value, $compress = false, $expire = null)
    {
        if (null === $expire)
        {
            $expire = isset($this->_config[0]['expire']) ? (int) $this->_config[0]['expire'] : 0;
        }
        return $this->_connection->replace($key, $value, $compress ? MEMCACHE_COMPRESSED : null, $expire);
    }

    /**
     * Delete a record or set a timeout
     *
     * @param string $key
     * @param int $timeout
     * @return bool
     */
    public function del($key, $timeout = 0)
    {
        return $this->delete($key, $timeout);
    }

    /**
     * Delete a record or set a timeout
     *
     * @param string $key
     * @param int $timeout
     * @return bool
     */
    public function delete($key, $timeout = 0)
    {
        return $this->_connection->delete($key, $timeout);
    }

    /**
     * Increment an existing integer value
     *
     * @param string $key
     * @param mixed $value
     * @return bool
     */
    public function incr($key, $value = 1)
    {
        return $this->increment($key, $value);
    }

    /**
     * Increment an existing integer value
     *
     * @param string $key
     * @param mixed $value
     * @return bool
     */
    public function increment($key, $value = 1)
    {
        return $this->_connection->increment($key, $value);
    }

    /**
     * Decrement an existing value
     *
     * @param string $key
     * @param mixed $value
     * @return bool
     */
    public function decr($key, $value = 1)
    {
        return $this->decrement($key, $value);
    }

    /**
     * Decrement an existing value
     *
     * @param string $key
     * @param mixed $value
     * @return bool
     */
    public function decrement($key, $value = 1)
    {
        return $this->_connection->decrement($key, $value);
    }

    /**
     * Clear the cache
     *
     * @return void
     */
    public function flush()
    {
        $this->_connection->flush();
    }

    /**
     * Close connection
     *
     * @return void
     */
    public function close()
    {
        $this->_connection->close();
    }

    /**
     * Gets memecache stats
     *
     * @return array
     */
    public function stats()
    {
        return $this->_connection->getStats();
    }
}

?>